#include <iostream>
#include <assert.h>
using namespace std;


template <class T>
struct BSTreeNode
{
	typedef BTreeNode<T> Node;
	Node* left;
	Node* right;
	T _val;
	Node(const T& val) :left(nullptr), right(nullptr), _val(val)
	{}
};

template<class T>
class BSTree
{
	typedef BSTreeNode<T> Node;
public:
	BSTree() = default;

	BSTree(const BSTree<T>& t)
	{
		_root = Copy(t._root);
	}

	BSTree<T>& operator=(BSTree<T>& t)
	{
		swap(_root, t._root);
		return *this;
	}

	~BSTree()
	{
		Destory(this->_root);
	}

	boolfind(const T& val)
	{
		Node* cur = _root;
		while (cur)
		{
			if (cur->_val < val)
			{
				cur = cur->right;
			}
			else if (cur->_val > val)
			{
				cur = cur->left;
			}
			else
			{
				return true;
			}
		}
		return false;
	}

	bool Insert(const T& val)
	{
		Node* cur = _root;
		if (cur == nullptr)
		{
			cur = new Node(val);
			_root = cur;
			return true;
		}
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			if (cur->_val < val)
			{
				cur = cur->right;
			}
			else if (cur->_val > val)
			{
				cur = cur->left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(val);
		if (parent->_val < val)
		{
			parent->right = cur;
		}
		else
		{
			parent->left = cur;
		}
		return true;
	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		_InOrder(root->left);
		cout << root->_val << " ";
		_InOrder(root->right);
	}

	void InOrder()
	{
		_InOrder(_root);
	}

	bool Erase(const T& val)
	{
		assert(_root);
		Node* cur = _root;
		Node* parent = cur;
		while (cur)
		{
			if (cur->_val < val)
			{
				parent = cur;
				cur = cur->right;
			}
			else if (cur->_val > val)
			{
				parent = cur;
				cur = cur->left;
			}
			else
			{
				if (cur->left == nullptr)
				{
					if (cur == _root)
					{
						_root = cur->right;
					}
					else
					{
						if (cur == parent->left)
						{
							parent->left = cur->right;
						}
						else
						{
							parent->right = cur->right;
						}
					}
				}
				else if (cur->right == nullptr)
				{
					if (cur == _root)
					{
						_root = cur->left;
					}
					else
					{
						if (cur == parent->right)
						{
							parent->right = cur->left;
						}
						else
						{
							parent->left = cur->left;
						}
					}
				}
				else
				{
					Node* rightMinParent = cur;
					Node* rightMin = cur->right;
					while (rightMin->left)
					{
						rightMinParent = rightMin;
						rightMin = rightMin->left;
					}
					cur->_val = rightMin->_val;
					if (rightMin == rightMinParent->left)
					{
						rightMinParent->left = rightMin->right;
					}
					else
					{
						rightMinParent->right = rightMin->right;
					}
					cur = rightMin;
				}
				delete cur;
				return true;
			}
		}
		return false;
	}

	void Destory(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		Destory(root->left);
		Destory(root->right);
		delete root;
	}
private:
	Node* Copy(Node* root)
	{
		if (root == nullptr)
		{
			return nullptr;
		}
		Node* newRoot = new Node(root->_val);
		newRoot->left = Copy(root->left);
		newRoot->right = Copy(root->right);
		return newRoot;
	}

	Node* _root;
};